package dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;

import javax.servlet.http.HttpSession;

import model.GroupInfo;
import model.LogInfo;
import model.MaskInfo;
import model.TableInfo;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import util.JdbcUtil;
import util.JsonUtil;

import common.Constants;

import exception.SystemException;

public class ScheduleInfoDao {

	private static final Log log = LogFactory.getLog(ScheduleInfoDao.class);
	
	private int progress = 0;
	
	public void updateToNewTable(HttpSession session, GroupInfo groupInfo) throws SystemException {
		List<TableInfo> tables = groupInfo.getGroupSource();
		Statement stmt = null;
		Connection conn = null;
		
		LogInfo logInfo = new LogInfo();
		logInfo.setOwner(groupInfo.getOwner());
		logInfo.setGroupName(groupInfo.getGroupName());
		
		try {
			conn = JdbcUtil.getConnection(session);
			conn.setAutoCommit(false);
			stmt = conn.createStatement();
			
			logInfo.setOperateName("excute");
			logInfo.setOperateDesc("开始脱敏" + groupInfo.getGroupName() + "分组中的数据...");
			addLogInfo(logInfo);
			
			String groupKey = groupInfo.getOwner() + "-" + groupInfo.getGroupName();
			
			for (int i = 0; i < tables.size(); i++) {
				TableInfo table = tables.get(i);
				session.setAttribute(groupKey, table);
				
				logInfo.setOperateName("excute");
				logInfo.setOperateDesc("开始脱敏表" + table.getTableName() + "中的数据...");
				addLogInfo(logInfo);
				
				JSONArray maskInfos = new MaskInfoDao().getMaskInfoByCondition(table.getOwner(), table.getTableName());
				JSONArray columns = getTableColumns(session, table.getOwner(), table.getTableName());
				JSONArray defaultValues = getColumnDefaultValues(session, table.getTableName());
				String tmpTableName = table.getTableName() + "_TMP";
				String bakTableName = table.getTableName() + "_BAK";
				
				String tableKey = table.getOwner() + "-" + table.getTableName();
				
				progress += 10/tables.size();
				session.setAttribute(tableKey, progress);
				
				JSONArray indexes = getTableIndexes(session, table.getOwner(), table.getTableName());
				JSONArray constraints = getTableConstraints(session, table.getOwner(), table.getTableName());
				JSONArray triggerNames = getTableTriggers(session, table.getOwner(), table.getTableName());
				JSONArray columnComments = getTableColumnComments(session, table.getTableName());
				JSONObject tableComments = getTableComments(session, table.getTableName());
				
				String[] indexDDL = getIndexesDDL(session, table.getOwner(), table.getTableName());
				String[] constraintDDL = getConstraintsDDL(session, table.getOwner(), table.getTableName());
				String[] refConstraintDDL = getRefConstraintsDDL(session, table.getOwner(), table.getTableName());
				String[] triggerDDL = getTriggerDDL(session, table.getOwner(), triggerNames);
				
				progress += 10/tables.size();
				session.setAttribute(tableKey, progress);
				
				deleteTable(session, table.getOwner(), tmpTableName);
				deleteTable(session, table.getOwner(), bakTableName);
				String columnStr = concactColumns(columns, maskInfos);
				String createTmpTableSql = "create table " + table.getOwner() + "." + tmpTableName + " parallel 16 nologging as (select " + columnStr + " from "+ table.getOwner() + "." + table.getTableName() + ")";
				log.debug(createTmpTableSql);
				stmt.addBatch(createTmpTableSql);
				String staticsSql = "ANALYZE TABLE " + table.getOwner() + "." + tmpTableName + " COMPUTE STATISTICS";
				log.debug(staticsSql);
				stmt.addBatch(staticsSql);
				
				String deleteTableDataSql = "truncate table " + table.getOwner() + "." + table.getTableName();
				log.debug(deleteTableDataSql);
				stmt.addBatch(deleteTableDataSql);
				
				String renameOriginateTableSql = "alter table " + table.getOwner() + "." + table.getTableName() + " rename to " + bakTableName;
				log.debug(renameOriginateTableSql);
				stmt.addBatch(renameOriginateTableSql);
				
				String renameTmpTable = "alter table " + table.getOwner() + "." + tmpTableName + " rename to " + table.getTableName();
				log.debug(renameTmpTable);
				stmt.addBatch(renameTmpTable);
				
				for (int j = 0; constraints != null && j < constraints.size(); j++) {
					String constraintName = constraints.getJSONObject(j).getString("CONSTRAINT_NAME");
					String dropConstraintSql = "alter table " + table.getOwner() + "." + bakTableName + " drop constraint " + constraintName;
					log.debug(dropConstraintSql);
					stmt.addBatch(dropConstraintSql);
				}
				
				for (int j = 0; indexes != null && j < indexes.size(); j++) {
					String indexName = indexes.getJSONObject(j).getString("INDEX_NAME");
					String dropIndexSql = "drop index " + table.getOwner() + "." + indexName;
					log.debug(dropIndexSql);
					stmt.addBatch(dropIndexSql);
				}
				
				for (int j = 0; triggerNames != null && j < triggerNames.size(); j++) {
					String triggerName = triggerNames.getJSONObject(j).getString("TRIGGER_NAME");
					String dropTriggerSql = "drop trigger " + table.getOwner() + "." + triggerName;
					log.debug(dropTriggerSql);
					stmt.addBatch(dropTriggerSql);
				}
				
				if (tableComments != null && tableComments.containsKey("COMMENTS")) {
					String commentTableSql = "comment on table " + table.getOwner() + "." + table.getTableName() + " is '" + tableComments.getString("COMMENTS") + "'";
					log.debug(commentTableSql);
					stmt.addBatch(commentTableSql);
				}
				
				for (int j = 0; j < columnComments.size(); j++) {
					String column = columnComments.getJSONObject(j).getString("COLUMN_NAME");
					String comments = columnComments.getJSONObject(j).getString("COMMENTS");
					String commentColumnSql = "comment on column " + table.getOwner() + "." + table.getTableName() + "." + column + " is '" + comments + "'";
					log.debug(commentColumnSql);
					stmt.addBatch(commentColumnSql);
				}
				
				for (int j = 0; j < defaultValues.size(); j++) {
					String column = defaultValues.getJSONObject(j).getString("COLUMN_NAME");
					String value = defaultValues.getJSONObject(j).getString("DATA_DEFAULT");
					String addDefaultValueSql = "alter table " + table.getOwner() + "." + table.getTableName() + " modify (" + column + " default " + value + ")";
					log.debug(addDefaultValueSql);
					stmt.addBatch(addDefaultValueSql);
				}
				
				if (indexDDL != null && indexDDL.length > 0) {
					for (int j = 0; j < indexDDL.length; j++) {
						String subDDL = indexDDL[j].trim();
						if (subDDL.length() > 0 && subDDL.indexOf("CREATE UNIQUE INDEX") == -1) {
							log.debug(subDDL);
							stmt.addBatch(subDDL);
						}
					}
				}
				
				if (constraintDDL != null && constraintDDL.length > 0) {
					for (int j = 0; j < constraintDDL.length; j++) {
						String subDDL = constraintDDL[j].trim();
						if (subDDL.length() > 0 && subDDL.indexOf("NOT NULL") == -1) {
							log.debug(subDDL);
							stmt.addBatch(subDDL);
						}
					}
				}
				
				if (refConstraintDDL != null && refConstraintDDL.length > 0) {
					for (int j = 0; j < refConstraintDDL.length; j++) {
						String subDDL = refConstraintDDL[j].trim();
						if (subDDL.length() > 0) {
							log.debug(subDDL);
							stmt.addBatch(subDDL);
						}
					}
				}
				
				if (triggerDDL != null && triggerDDL.length > 0) {
					for (int j = 0; j < triggerDDL.length; j++) {
						String subDDL = triggerDDL[j].trim();
						if (subDDL.length() > 0) {
							log.debug(subDDL);
							stmt.addBatch(subDDL);
						}
					}
				}
				
				progress += 10/tables.size();
				session.setAttribute(tableKey, progress);
				
				stmt.executeBatch();
				JdbcUtil.commitConnection(conn); 
				
				logInfo.setOperateName("complete");
				logInfo.setOperateDesc("表" + table.getTableName() + "中的数据脱敏成功...");
				addLogInfo(logInfo);
				stmt.clearBatch();
				
				progress = (i + 1) * 100/tables.size();
				session.setAttribute(tableKey, progress);
				
				log.debug(table.getTableName() + ", progress:" + progress);
			}
			
			logInfo.setOperateName("complete");
			logInfo.setOperateDesc("分组" + groupInfo.getGroupName() + "中的数据脱敏完毕...");
			addLogInfo(logInfo);
			log.debug("批处理完成");
		} catch (SQLException e) {
			e.printStackTrace();
			JdbcUtil.rollbackConnection(conn);
			logInfo.setOperateName("error");
			logInfo.setOperateDesc("分组" + groupInfo.getGroupName() + "中的数据脱敏失败..." + e.getMessage());
			addLogInfo(logInfo);
			throw new SystemException(e);
		} finally {
			if (stmt != null) {
				try {
					stmt.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
			try {
				conn.setAutoCommit(true); 
				JdbcUtil.closeConnection(conn);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
	
	public JSONObject loadProgress(HttpSession session, GroupInfo groupInfo) {
		JSONObject result = new JSONObject();
		
		String groupKey = groupInfo.getOwner() + "-" + groupInfo.getGroupName();
		
		TableInfo currentTable = null;
		int currentProgress = 0;
		
		if (session.getAttribute(groupKey) != null) {
			currentTable = (TableInfo)session.getAttribute(groupKey);
		}
		if (currentTable == null) {
			result.put("PROGRESS", currentProgress);
			return result;
		}
		String tableKey = currentTable.getOwner() + "-" + currentTable.getTableName();
		if (session.getAttribute(tableKey) != null) {
			currentProgress = Integer.parseInt(session.getAttribute(tableKey).toString());
		}
		
		LogInfo logInfo = new LogInfo();
		logInfo.setOwner(groupInfo.getOwner());
		logInfo.setGroupName(groupInfo.getGroupName());
		
		Connection conn = JdbcUtil.getConnection(session);
		String sql = " SELECT TRUNC(SOFAR / TOTALWORK * 100, 0) as progress from V$SESSION_LONGOPS where target=upper('" + currentTable.getOwner() + "." + currentTable.getTableName() + "')";
		log.debug(sql);
		try {
			PreparedStatement pstmt = conn.prepareStatement(sql);
			ResultSet resultSet = pstmt.executeQuery();
			result = JsonUtil.formatRsToJsonObject(resultSet);
			if (result.containsKey("PROGRESS") && result.get("PROGRESS") != null) {
				int percent = Integer.parseInt(result.get("PROGRESS").toString());
				log.debug(percent);
				result.put("PROGRESS", currentProgress + percent  / (70 * groupInfo.getGroupSource().size()));
			} else {
				result.put("PROGRESS", currentProgress);
			}
			return result;
		} catch (Exception e) {
			e.printStackTrace();
			logInfo.setOperateName("error");
			logInfo.setOperateDesc("分组" + groupInfo.getGroupName() + "中的执行进度获取失败..." + e.getMessage());
			addLogInfo(logInfo);
			result.put("PROGRESS", currentProgress);
			return result;
		} finally {
			try {
				JdbcUtil.closeConnection(conn);
			} catch (Exception e) {
				e.printStackTrace();
				throw new SystemException(e);
			}
		}
	}
	
	private void addLogInfo(LogInfo logInfo) {
		try {
			new LogInfoDao().addLogInfo(logInfo);
		} catch (SystemException e) {
			e.printStackTrace();
		}
	}
	
	private int deleteTable(HttpSession session, String schema, String tableName) {
		Connection conn = JdbcUtil.getConnection(session);
		String sql = "drop table " + schema + "." + tableName;
		log.debug(sql);
		try {
			PreparedStatement pstmt = conn.prepareStatement(sql);
			return pstmt.executeUpdate();
		} catch (Exception e) {
			log.error(e.getMessage());
			return 0;
		} finally {
			try {
				JdbcUtil.closeConnection(conn);
			} catch (Exception e) {
				e.printStackTrace();
				throw new SystemException(e);
			}
		}
	}
	
	private JSONArray getTableColumns(HttpSession session, String schema, String tableName) {
		String sql = "select column_name from all_tab_columns where owner=upper('" + schema  + "') and table_name=upper('" + tableName + "')";
		Connection conn = JdbcUtil.getConnection(session);
		log.debug(sql);
		try {
			PreparedStatement pstmt = conn.prepareStatement(sql);
			ResultSet resultSet = pstmt.executeQuery();
			return JsonUtil.formatRsToJsonArray(resultSet);
		} catch (Exception e) {
			e.printStackTrace();
			throw new SystemException(e);
		} finally {
			try {
				JdbcUtil.closeConnection(conn);
			} catch (Exception e) {
				e.printStackTrace();
				throw new SystemException(e);
			}
		}
	}
	
	private JSONArray getTableIndexes(HttpSession session, String schema, String tableName) {
		String sql = "select index_name from dba_indexes where table_owner=upper('" + schema  + "') and table_name=upper('" + tableName + "') and uniqueness='NONUNIQUE'";
		Connection conn = JdbcUtil.getConnection(session);
		log.debug(sql);
		try {
			PreparedStatement pstmt = conn.prepareStatement(sql);
			ResultSet resultSet = pstmt.executeQuery();
			return JsonUtil.formatRsToJsonArray(resultSet);
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		} finally {
			try {
				JdbcUtil.closeConnection(conn);
			} catch (Exception e) {
				e.printStackTrace();
				throw new SystemException(e);
			}
		}
	}
	
	private JSONArray getTableConstraints(HttpSession session, String schema, String tableName) {
		String sql = "select constraint_name from dba_constraints where owner=upper('" + schema  + "') and table_name=upper('" + tableName + "') and (constraint_type = 'R' or constraint_type = 'P')";
		Connection conn = JdbcUtil.getConnection(session);
		log.debug(sql);
		try {
			PreparedStatement pstmt = conn.prepareStatement(sql);
			ResultSet resultSet = pstmt.executeQuery();
			return JsonUtil.formatRsToJsonArray(resultSet);
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		} finally {
			try {
				JdbcUtil.closeConnection(conn);
			} catch (Exception e) {
				e.printStackTrace();
				throw new SystemException(e);
			}
		}
	}
	
	private JSONArray getTableTriggers(HttpSession session, String schema, String tableName) {
		String sql = "select trigger_name from dba_triggers where table_owner=upper('" + schema  + "') and table_name=upper('" + tableName + "')";
		Connection conn = JdbcUtil.getConnection(session);
		log.debug(sql);
		try {
			PreparedStatement pstmt = conn.prepareStatement(sql);
			ResultSet resultSet = pstmt.executeQuery();
			return JsonUtil.formatRsToJsonArray(resultSet);
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		} finally {
			try {
				JdbcUtil.closeConnection(conn);
			} catch (Exception e) {
				e.printStackTrace();
				throw new SystemException(e);
			}
		}
	}
	
	private JSONObject getTableComments(HttpSession session, String tableName) {
		String sql = "select comments from dba_tab_comments where table_name=upper('" + tableName + "') and comments is not null";
		Connection conn = JdbcUtil.getConnection(session);
		log.debug(sql);
		try {
			PreparedStatement pstmt = conn.prepareStatement(sql);
			ResultSet resultSet = pstmt.executeQuery();
			return JsonUtil.formatRsToJsonObject(resultSet);
		} catch (Exception e) {
			e.printStackTrace();
			throw new SystemException(e);
		} finally {
			try {
				JdbcUtil.closeConnection(conn);
			} catch (Exception e) {
				e.printStackTrace();
				throw new SystemException(e);
			}
		}
	}
	
	private JSONArray getTableColumnComments(HttpSession session, String tableName) {
		String sql = "select column_name, comments from dba_col_comments where table_name=upper('" + tableName + "') and comments is not null";
		Connection conn = JdbcUtil.getConnection(session);
		log.debug(sql);
		try {
			PreparedStatement pstmt = conn.prepareStatement(sql);
			ResultSet resultSet = pstmt.executeQuery();
			return JsonUtil.formatRsToJsonArray(resultSet);
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		} finally {
			try {
				JdbcUtil.closeConnection(conn);
			} catch (Exception e) {
				e.printStackTrace();
				throw new SystemException(e);
			}
		}
	}
	
	private JSONArray getColumnDefaultValues(HttpSession session, String tableName) { 
		String sql = "select column_name, data_default from dba_tab_columns where table_name=upper('" + tableName + "') and data_default is not null";
		Connection conn = JdbcUtil.getConnection(session);
		log.debug(sql);
		try {
			PreparedStatement pstmt = conn.prepareStatement(sql);
			ResultSet resultSet = pstmt.executeQuery();
			return JsonUtil.formatRsToJsonArray(resultSet);
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		} finally {
			try {
				JdbcUtil.closeConnection(conn);
			} catch (Exception e) {
				e.printStackTrace();
				throw new SystemException(e);
			}
		}
	}
	
	private String[] getIndexesDDL(HttpSession session, String schema, String tableName) {
		String sql = "select dbms_metadata.get_dependent_ddl('INDEX', upper('" + tableName + "'), upper('" + schema + "')) output from dual";
		Connection conn = JdbcUtil.getConnection(session);
		log.debug(sql);
		String[] sqls = null;
		try {
			PreparedStatement pstmt = conn.prepareStatement(sql);
			ResultSet resultSet = pstmt.executeQuery();
			JSONObject rs = JsonUtil.formatRsToJsonObject(resultSet);
			if (rs != null && rs.containsKey("OUTPUT")) {
				String str = rs.getString("OUTPUT");
				sqls = str.split("\n \n");
			}
			return sqls;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		} finally {
			try {
				JdbcUtil.closeConnection(conn);
			} catch (Exception e) {
				e.printStackTrace();
				throw new SystemException(e);
			}
		}
	}
	
	private String[] getConstraintsDDL(HttpSession session, String schema, String tableName) {
		String sql = "select dbms_metadata.get_dependent_ddl('CONSTRAINT', upper('" + tableName + "'), upper('" + schema + "')) output from dual";
		Connection conn = JdbcUtil.getConnection(session);
		String[] sqls = null;
		try {
			PreparedStatement pstmt = conn.prepareStatement(sql);
			ResultSet resultSet = pstmt.executeQuery();
			JSONObject rs = JsonUtil.formatRsToJsonObject(resultSet);
			if (rs != null && rs.containsKey("OUTPUT")) {
				String str = rs.getString("OUTPUT");
				sqls = str.split("\n \n");
			}
			return sqls;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		} finally {
			try {
				JdbcUtil.closeConnection(conn);
			} catch (Exception e) {
				e.printStackTrace();
				throw new SystemException(e);
			}
		}
	}
	
	private String[] getTriggerDDL(HttpSession session, String schema, JSONArray triggerNames) {
		Connection conn = JdbcUtil.getConnection(session);
		String[] sqls = new String[triggerNames.size()];
		try {
			for(int i = 0; i < triggerNames.size(); i++) {
				String triggerName = triggerNames.getJSONObject(i).getString("TRIGGER_NAME");
				String sql = "select dbms_metadata.get_ddl('TRIGGER', upper('" + triggerName + "'), upper('" + schema + "')) output from dual";
				PreparedStatement pstmt = conn.prepareStatement(sql);
				ResultSet resultSet = pstmt.executeQuery();
				JSONObject rs = JsonUtil.formatRsToJsonObject(resultSet);
				if (rs != null && rs.containsKey("OUTPUT")) {
					sqls[i] = rs.getString("OUTPUT");
				}
			}
			return sqls;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		} finally {
			try {
				JdbcUtil.closeConnection(conn);
			} catch (Exception e) {
				e.printStackTrace();
				throw new SystemException(e);
			}
		}
	}
	
	private String[] getRefConstraintsDDL(HttpSession session, String schema, String tableName) {
		String sql = "select dbms_metadata.get_dependent_ddl('REF_CONSTRAINT', upper('" + tableName + "'), upper('" + schema + "')) output from dual";
		Connection conn = JdbcUtil.getConnection(session);
		String[] sqls = null;
		try {
			PreparedStatement pstmt = conn.prepareStatement(sql);
			ResultSet resultSet = pstmt.executeQuery();
			JSONObject rs = JsonUtil.formatRsToJsonObject(resultSet);
			if (rs != null && rs.containsKey("OUTPUT")) {
				String str = rs.getString("OUTPUT");
				sqls = str.split("\n \n");
			}
			return sqls;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		} finally {
			try {
				JdbcUtil.closeConnection(conn);
			} catch (Exception e) {
				e.printStackTrace();
				throw new SystemException(e);
			}
		}
	}
	
	private String concactColumns(JSONArray ja, JSONArray maskInfos) {
		String[] columns = new String[ja.size()]; 
		for (int i = 0; i < ja.size(); i++) {
			JSONObject col = ja.getJSONObject(i);
			String column = col.getString("COLUMN_NAME");
			columns[i] = column;
			if (maskInfos != null) {
				for (int j = 0; j < maskInfos.size(); j++) {
					JSONObject jo = maskInfos.getJSONObject(j);
					MaskInfo maskInfo = json2MaskInfo(jo);
					String tabColumn = maskInfo.getTabColumn();
					if (column.equals(tabColumn.toUpperCase())) {
						if (maskInfo.getFuncParam() != null && !maskInfo.getFuncParam().isEmpty()) {
							columns[i] = Constants.ADMIN_USER_NAME + "." + maskInfo.getFuncName() + "(" + column + ",'" + maskInfo.getFuncParam() + "') as " + column;
						} else {
							columns[i] = Constants.ADMIN_USER_NAME + "." + maskInfo.getFuncName() + "(" + column + ") as " + column;
						}
						break;
					}
				}
			}
		}
		return StringUtils.join(columns, ",");
	}
	
	private MaskInfo json2MaskInfo(JSONObject jo) {
		MaskInfo maskInfo = new MaskInfo();
		maskInfo.setMid(jo.getString("MID"));
		maskInfo.setOwner(jo.getString("OWNER"));
		maskInfo.setTabName(jo.getString("TAB_NAME"));
		maskInfo.setTabColumn(jo.getString("TAB_COLUMN"));
		maskInfo.setFuncName(jo.getString("FUNC_NAME"));
		maskInfo.setFuncParam(jo.containsKey("FUNC_PARAM") ? jo.getString("FUNC_PARAM") : "");
		maskInfo.setFuncComment(jo.containsKey("FUNC_COMMENT") ? jo.getString("FUNC_COMMENT") : "");
		return maskInfo;
	}
	
	public static void main(String[] args) {
		String schema = "system";
		String tableName = "help";
		Connection conn = JdbcUtil.getConnection(Constants.ORACLE_DB_DRIVER, "modudf_test", "modudf_test");
//		String tableName = "testPrivacy";
//		String schema = "system";
//		String sql = "create table " + schema + "." + tableName + "_bak as select * from " + schema + "."  + tableName + " where 1=2";
//		log.debug(sql);
		
		String sql = "select dbms_metadata.get_dependent_ddl('CONSTRAINT', upper('" + tableName + "'), upper('" + schema + "')) output from dual";
//		String sql = "select index_name from user_indexes where table_owner=upper('" + "modudf_test"  + "') and table_name=upper('" + "AFCS_AGENT" + "')";
		log.debug(sql);
		try {
			PreparedStatement pstmt = conn.prepareStatement(sql);
			ResultSet resultSet = pstmt.executeQuery();
			System.out.println(JsonUtil.formatRsToJsonObject(resultSet).toString());
		} catch (Exception e) {
			e.printStackTrace();
			throw new SystemException(e);
		} finally {
			try {
				JdbcUtil.closeConnection(conn);
			} catch (Exception e) {
				e.printStackTrace();
				throw new SystemException(e);
			}
		}
	}

}
